/**
 * 贪吃蛇游戏 - 使用PixiJS实现
 * 游戏结构按照通用游戏模块开发模式设计
 */

// 游戏常量
const GRID_SIZE = 20; // 网格大小
const GRID_COUNT = 25; // 20x20的网格，减小网格数量以适应屏幕
const GAME_SPEED = 150; // 初始游戏速度(毫秒)
const GAME_WIDTH = GRID_SIZE * GRID_COUNT; // 游戏宽度
const GAME_HEIGHT = GRID_SIZE * GRID_COUNT; // 游戏高度
const DIRECTIONS = {
    UP: { x: 0, y: -1 },
    DOWN: { x: 0, y: 1 },
    LEFT: { x: -1, y: 0 },
    RIGHT: { x: 1, y: 0 }
};

// 颜色常量
const COLORS = {
    SNAKE_HEAD: 0x4CAF50,
    SNAKE_BODY: 0x8BC34A,
    SNAKE_BORDER: 0x388E3C,
    FOOD: 0xFF5722,
    GRID: 0xf5f5f5,
    BACKGROUND: 0xFFFFFF
};

/**
 * 关卡类 - 管理游戏关卡和障碍物
 */
class Level {
    constructor(levelNumber) {
        this.levelNumber = levelNumber || 1;
        this.obstacles = [];
        this.initObstacles();
    }
    
    initObstacles() {
        this.obstacles = [];
        // 根据关卡数生成障碍物
        const obstacleCount = Math.min(this.levelNumber * 2, 20); // 最多20个障碍物
        
        for (let i = 0; i < obstacleCount; i++) {
            let newObstacle;
            let positionValid;
            
            // 生成不与已有障碍物和其他元素重叠的位置
            do {
                positionValid = true;
                newObstacle = {
                    x: Math.floor(Math.random() * GRID_COUNT),
                    y: Math.floor(Math.random() * GRID_COUNT)
                };
                
                // 检查是否与已有的障碍物重叠
                for (const obstacle of this.obstacles) {
                    if (obstacle.x === newObstacle.x && obstacle.y === newObstacle.y) {
                        positionValid = false;
                        break;
                    }
                }
            } while (!positionValid);
            
            this.obstacles.push(newObstacle);
        }
        console.log('Level:', this.levelNumber, 'Obstacles:', this.obstacles);
    }
    
    // 根据分数更新关卡
    updateLevel(score) {
        const newLevel = Math.max(1, Math.floor(score / 10) + 1); // 每50分升一级
        if (newLevel !== this.levelNumber) {
            this.levelNumber = newLevel;
            this.initObstacles();
            return true; // 表示关卡已更新
        }
        return false; // 表示关卡未更新
    }
    
    // 检查指定位置是否是障碍物
    isObstacle(x, y) {
        return this.obstacles.some(obstacle => obstacle.x === x && obstacle.y === y);
    }
}

/**
 * 游戏管理器 - 负责游戏的主要逻辑和状态管理
 */
class GameManager {
    constructor() {
        // 初始化游戏组件
        this.renderer = new Renderer();
        this.inputManager = new InputManager();
        this.snake = new Snake();
        this.food = new Food();
        
        // 游戏状态
        this.score = 0;
        this.isGameOver = false;
        this.gameLoopInterval = null;
        
        // 初始化游戏
        this.init();
    }
    
    init() {
        // 设置初始状态
        this.score = 0;
        this.isGameOver = false;
        document.getElementById('score').textContent = '0';
        document.getElementById('game-over').style.display = 'none';
        
        // 获取选中的关卡
        const levelSelect = document.getElementById('level-select');
        const selectedLevel = levelSelect ? parseInt(levelSelect.value) : 1;
        
        // 初始化关卡
        this.level = new Level(selectedLevel);
        
        // 初始化蛇和食物
        this.snake.init();
        this.food.generate(this.snake.body, this.level.obstacles); // 传入障碍物以避免重叠
        
        // 设置输入监听
        this.inputManager.setDirectionChangeCallback(this.changeDirection.bind(this));
        
        // 初始化渲染器
        this.renderer.init();
        
        // 渲染初始状态
        this.renderer.render(this.snake.body, this.food.position, this.level.obstacles);
        
        // 启动游戏循环
        this.startGameLoop();
    }
    
    startGameLoop() {
        // 清除可能存在的旧循环
        if (this.gameLoopInterval) {
            clearInterval(this.gameLoopInterval);
        }
        
        // 设置新的游戏循环
        this.gameLoopInterval = setInterval(() => {
            this.update();
        }, GAME_SPEED);
    }
    
    update() {
        if (this.isGameOver) return;
        
        // 移动蛇
        this.snake.move();
        
        // 检查是否吃到食物
        if (this.checkFoodCollision()) {
            // 增加蛇的长度
            this.snake.grow();
            
            // 生成新的食物
            this.food.generate(this.snake.body, this.level.obstacles);
            
            // 更新分数
            this.score += 10;
            document.getElementById('score').textContent = this.score;
            
            // 检查是否需要升级
            if (this.level.updateLevel(this.score)) {
                // 重新生成食物以避免与新障碍物重叠
                this.food.generate(this.snake.body, this.level.obstacles);
            }
        }
        
        // 检查碰撞
        if (this.checkCollision()) {
            this.gameOver();
            return;
        }
        
        // 渲染游戏状态
        this.renderer.render(this.snake.body, this.food.position, this.level.obstacles);
    }
    
    checkFoodCollision() {
        const head = this.snake.body[0];
        const collision = head.x === this.food.position.x && head.y === this.food.position.y;
        
        // 如果发生碰撞，创建粒子效果
        if (collision) {
            this.renderer.createFoodParticles(this.food.position);
        }
        
        return collision;
    }
    
    checkCollision() {
        const head = this.snake.body[0];
        
        // 检查是否撞墙
        if (head.x < 0 || head.x >= GRID_COUNT || head.y < 0 || head.y >= GRID_COUNT) {
            return true;
        }
        
        // 检查是否撞到自己（从第二个身体部分开始检查）
        for (let i = 1; i < this.snake.body.length; i++) {
            if (head.x === this.snake.body[i].x && head.y === this.snake.body[i].y) {
                return true;
            }
        }
        
        // 检查是否撞到障碍物
        if (this.level.isObstacle(head.x, head.y)) {
            return true;
        }
        
        return false;
    }
    
    changeDirection(direction) {
        this.snake.changeDirection(direction);
    }
    
    gameOver() {
        this.isGameOver = true;
        clearInterval(this.gameLoopInterval);
        
        // 显示游戏结束界面
        document.getElementById('final-score').textContent = this.score;
        document.getElementById('game-over').style.display = 'block';
    }
    
    restart() {
        // 清除旧的渲染内容
        this.renderer.destroy();
        
        // 获取选中的关卡
        const levelSelect = document.getElementById('level-select');
        const selectedLevel = levelSelect ? parseInt(levelSelect.value) : 1;
        
        // 重新初始化关卡
        this.level = new Level(selectedLevel);
        
        // 重新初始化游戏
        this.init();
    }
}

/**
 * 渲染器 - 负责游戏的视觉呈现，使用PixiJS
 */
class Renderer {
    constructor() {
        // PixiJS应用实例
        this.app = null;
        
        // 游戏容器
        this.gameContainer = null;
        
        // 网格容器
        this.gridContainer = null;
        
        // 蛇容器
        this.snakeContainer = null;
        
        // 食物精灵
        this.foodSprite = null;
        
        // 障碍物容器
        this.obstaclesContainer = null;
        
        // 粒子容器
        this.particlesContainer = null;
        
        // 粒子数组
        this.particles = [];
    }
    
    init() {
        // 创建PixiJS应用
        this.app = new PIXI.Application({
            width: GAME_WIDTH,
            height: GAME_HEIGHT,
            backgroundColor: COLORS.BACKGROUND,
            resolution: window.devicePixelRatio || 1,
            antialias: true
        });
        
        // 将PixiJS创建的canvas添加到DOM中
        document.getElementById('game-board').appendChild(this.app.view);
        
        // 创建游戏容器
        this.gameContainer = new PIXI.Container();
        this.app.stage.addChild(this.gameContainer);
        
        // 创建网格容器
        this.gridContainer = new PIXI.Container();
        this.gameContainer.addChild(this.gridContainer);
        
        // 创建障碍物容器
        this.obstaclesContainer = new PIXI.Container();
        this.gameContainer.addChild(this.obstaclesContainer);
        
        // 创建蛇容器
        this.snakeContainer = new PIXI.Container();
        this.gameContainer.addChild(this.snakeContainer);
        
        // 创建粒子容器
        this.particlesContainer = new PIXI.Container();
        this.gameContainer.addChild(this.particlesContainer);
        
        // 初始化粒子数组
        this.particles = [];
        
        // 设置游戏循环更新粒子
        this.app.ticker.add(() => this.updateParticles());
        
        // 绘制网格
        this.drawGrid();
    }
    
    render(snakeBody, foodPosition, obstacles) {
        // 渲染障碍物
        this.renderObstacles(obstacles);
        
        // 渲染蛇
        this.renderSnake(snakeBody);
        
        // 渲染食物
        this.renderFood(foodPosition);
    }
    
    drawGrid() {
        // 清除旧的网格
        this.gridContainer.removeChildren();
        
        // 创建网格图形
        const grid = new PIXI.Graphics();
        grid.lineStyle(0.5, COLORS.GRID);
        
        // 绘制垂直线
        for (let i = 0; i <= GRID_COUNT; i++) {
            grid.moveTo(i * GRID_SIZE, 0);
            grid.lineTo(i * GRID_SIZE, GAME_HEIGHT);
        }
        
        // 绘制水平线
        for (let i = 0; i <= GRID_COUNT; i++) {
            grid.moveTo(0, i * GRID_SIZE);
            grid.lineTo(GAME_WIDTH, i * GRID_SIZE);
        }
        
        // 添加到网格容器
        this.gridContainer.addChild(grid);
    }
    
    renderSnake(snakeBody) {
        // 清除旧的蛇
        this.snakeContainer.removeChildren();
        
        // 绘制蛇的每个部分
        snakeBody.forEach((segment, index) => {
            // 创建蛇的一个部分
            const snakePart = new PIXI.Graphics();
            
            // 设置填充颜色（头部和身体不同）
            const fillColor = index === 0 ? COLORS.SNAKE_HEAD : COLORS.SNAKE_BODY;
            
            // 绘制矩形
            snakePart.beginFill(fillColor);
            snakePart.lineStyle(1, COLORS.SNAKE_BORDER);
            snakePart.drawRect(0, 0, GRID_SIZE, GRID_SIZE);
            snakePart.endFill();
            
            // 设置位置
            snakePart.x = segment.x * GRID_SIZE;
            snakePart.y = segment.y * GRID_SIZE;
            
            // 添加到蛇容器
            this.snakeContainer.addChild(snakePart);
        });
    }
    
    renderFood(position) {
        // 如果食物精灵已存在，则移除
        if (this.foodSprite) {
            this.gameContainer.removeChild(this.foodSprite);
        }
        
        // 创建食物精灵
        this.foodSprite = new PIXI.Graphics();
        this.foodSprite.beginFill(COLORS.FOOD);
        this.foodSprite.drawCircle(GRID_SIZE / 2, GRID_SIZE / 2, GRID_SIZE / 2 - 2);
        this.foodSprite.endFill();
        
        // 设置位置
        this.foodSprite.x = position.x * GRID_SIZE;
        this.foodSprite.y = position.y * GRID_SIZE;
        
        // 添加到游戏容器
        this.gameContainer.addChild(this.foodSprite);
    }
    
    renderObstacles(obstacles) {
        // 清除旧的障碍物
        this.obstaclesContainer.removeChildren();
        
        // 绘制障碍物
        obstacles.forEach(obstacle => {
            const obstacleSprite = new PIXI.Graphics();
            obstacleSprite.beginFill(COLORS.OBSTACLE);
            obstacleSprite.lineStyle(1, COLORS.OBSTACLE_BORDER);
            obstacleSprite.drawRect(0, 0, GRID_SIZE, GRID_SIZE);
            obstacleSprite.endFill();
            
            // 设置位置
            obstacleSprite.x = obstacle.x * GRID_SIZE;
            obstacleSprite.y = obstacle.y * GRID_SIZE;
            
            // 添加到障碍物容器
            this.obstaclesContainer.addChild(obstacleSprite);
        });
    }
    
    createFoodParticles(position) {
        // 在食物位置创建粒子效果
        const particleCount = 20; // 粒子数量
        const particleColors = [0xFF5722, 0xFFC107, 0xFFEB3B]; // 粒子颜色
        
        for (let i = 0; i < particleCount; i++) {
            // 创建粒子
            const particle = new PIXI.Graphics();
            
            // 随机选择颜色
            const colorIndex = Math.floor(Math.random() * particleColors.length);
            particle.beginFill(particleColors[colorIndex]);
            
            // 随机粒子大小
            const size = Math.random() * 4 + 2;
            particle.drawCircle(0, 0, size);
            particle.endFill();
            
            // 设置粒子位置（食物的中心位置）
            particle.x = position.x * GRID_SIZE + GRID_SIZE / 2;
            particle.y = position.y * GRID_SIZE + GRID_SIZE / 2;
            
            // 设置粒子速度和生命周期
            particle.vx = (Math.random() - 0.5) * 5;
            particle.vy = (Math.random() - 0.5) * 5;
            particle.alpha = 1;
            particle.life = 30; // 粒子生命周期（帧数）
            
            // 添加到粒子容器
            this.particlesContainer.addChild(particle);
            this.particles.push(particle);
        }
    }
    
    updateParticles() {
        // 更新所有粒子
        for (let i = this.particles.length - 1; i >= 0; i--) {
            const particle = this.particles[i];
            
            // 更新粒子位置
            particle.x += particle.vx;
            particle.y += particle.vy;
            
            // 减少生命周期
            particle.life--;
            
            // 逐渐降低透明度
            particle.alpha = particle.life / 30;
            
            // 如果生命周期结束，移除粒子
            if (particle.life <= 0) {
                this.particlesContainer.removeChild(particle);
                this.particles.splice(i, 1);
            }
        }
    }
    
    destroy() {
        // 销毁PixiJS应用
        if (this.app) {
            this.app.destroy(true, {
                children: true,
                texture: true,
                baseTexture: true
            });
        }
    }
}

/**
 * 输入管理器 - 处理用户输入
 */
class InputManager {
    constructor() {
        this.directionChangeCallback = null;
        this.setupEventListeners();
    }
    
    setupEventListeners() {
        // 使用原生JavaScript监听键盘事件
        document.addEventListener('keydown', (event) => {
            this.handleKeyDown(event);
        });
        
        // 使用原生JavaScript监听重新开始按钮
        document.getElementById('restart-button').addEventListener('click', () => {
            if (window.gameManager) {
                window.gameManager.restart();
            }
        });
    }
    
    handleKeyDown(event) {
        if (!this.directionChangeCallback) return;
        
        // 根据按键设置方向
        switch (event.key) {
            case 'ArrowUp':
                this.directionChangeCallback(DIRECTIONS.UP);
                break;
            case 'ArrowDown':
                this.directionChangeCallback(DIRECTIONS.DOWN);
                break;
            case 'ArrowLeft':
                this.directionChangeCallback(DIRECTIONS.LEFT);
                break;
            case 'ArrowRight':
                this.directionChangeCallback(DIRECTIONS.RIGHT);
                break;
        }
    }
    
    setDirectionChangeCallback(callback) {
        this.directionChangeCallback = callback;
    }
}

/**
 * 蛇 - 表示玩家控制的蛇
 */
class Snake {
    constructor() {
        this.body = [];
        this.direction = DIRECTIONS.RIGHT;
        this.nextDirection = DIRECTIONS.RIGHT;
        this.growing = false;
    }
    
    init() {
        // 初始化蛇的身体（3个单位长）
        this.body = [
            { x: 5, y: 12 },
            { x: 4, y: 12 },
            { x: 3, y: 12 }
        ];
        this.direction = DIRECTIONS.RIGHT;
        this.nextDirection = DIRECTIONS.RIGHT;
        this.growing = false;
    }
    
    move() {
        // 更新方向
        this.direction = this.nextDirection;
        
        // 计算新的头部位置
        const head = { x: this.body[0].x + this.direction.x, y: this.body[0].y + this.direction.y };
        
        // 将新头部添加到身体前面
        this.body.unshift(head);
        
        // 如果不是在生长，则移除尾部
        if (!this.growing) {
            this.body.pop();
        } else {
            this.growing = false;
        }
    }
    
    changeDirection(newDirection) {
        // 防止180度转弯（不能直接反向移动）
        if (this.direction.x + newDirection.x === 0 && this.direction.y + newDirection.y === 0) {
            return;
        }
        
        this.nextDirection = newDirection;
    }
    
    grow() {
        this.growing = true;
    }
}

/**
 * 食物 - 表示蛇可以吃的食物
 */
class Food {
    constructor() {
        this.position = { x: 0, y: 0 };
    }
    
    generate(snakeBody, obstacles) {
        let newPosition;
        let positionValid;
        
        // 生成不与蛇身体和障碍物重叠的随机位置
        do {
            positionValid = true;
            newPosition = {
                x: Math.floor(Math.random() * GRID_COUNT),
                y: Math.floor(Math.random() * GRID_COUNT)
            };
            
            // 检查是否与蛇身体重叠
            for (const segment of snakeBody) {
                if (segment.x === newPosition.x && segment.y === newPosition.y) {
                    positionValid = false;
                    break;
                }
            }
            
            // 如果位置仍然有效，检查是否与障碍物重叠
            if (positionValid && obstacles) {
                for (const obstacle of obstacles) {
                    if (obstacle.x === newPosition.x && obstacle.y === newPosition.y) {
                        positionValid = false;
                        break;
                    }
                }
            }
        } while (!positionValid);
        
        this.position = newPosition;
    }
}

// 游戏启动 - 使用原生JavaScript监听DOM加载完成
window.addEventListener('load', () => {
    // 创建并启动游戏
    window.gameManager = new GameManager();
});